import java.io.*;
import java.util.Scanner;

/*
 ID: ning yusui
 LANG: JAVA
 TASK: cowtour
 */

public class cowtour {
    Scanner in;
    PrintWriter out;
    public static final double INF = -1;
    private Point[] points;
    private char[][] adjMat;
    private double[][] distMat;
    private int pointSize;
    private double[] maxDist;
    private double[] diameter;

    public cowtour() throws IOException {
        in = new Scanner(new File(this.getClass().getName() + ".in"));
        out = new PrintWriter(new BufferedWriter(new FileWriter(this.getClass().getName() +
                ".out")));
    }

    private void work() {
        input();
        calcDistMat();
        floyd();
        calcMaxDist();
        calcDiameter();
        double minD = minDiameter();
        out.println(String.format("%06f", minD));
        out.flush();
        out.close();
    }

    private double minDiameter() {
        double minDiameter = INF;
        for (int i = 0; i < pointSize; i++) {
            for (int j = i + 1; j < pointSize; j++) {
                if (distMat[i][j] < 0) {
                    double mayDiaij = maxDist[i] + calcDistance(i, j) + maxDist[j];
                    double diaij = Math.max(mayDiaij, Math.max(diameter[i], diameter[j]));
                    if (minDiameter < 0 || minDiameter > diaij) {
                        minDiameter = diaij;
                    }
                }
            }
        }
        return minDiameter;
    }

    private void calcDiameter() {
        diameter = new double[pointSize];
        for (int i = 0; i < pointSize; i++) {
            diameter[i] = maxDist[i];
            for (int j = 0; j < pointSize; j++) {
                if (distMat[i][j] > 0) {
                    if (diameter[i] < maxDist[j]) {
                        diameter[i] = maxDist[j];
                    }
                }
            }
        }
    }

    private void calcMaxDist() {
        maxDist = new double[pointSize];
        for (int i = 0; i < pointSize; i++) {
            for (int j = 0; j < pointSize; j++) {
                if (maxDist[i] < distMat[i][j]) {
                    maxDist[i] = distMat[i][j];
                }
            }
        }
    }

    private void floyd() {
        for (int j = 0; j < pointSize; j++) {
            for (int i = 0; i < pointSize; i++) {
                for (int k = 0; k < pointSize; k++) {
                    if (distMat[i][j] > 0 && distMat[j][k] > 0) {
                        double dist = distMat[i][j] + distMat[j][k];
                        if (distMat[i][k] < 0 || dist < distMat[i][k]) {
                            distMat[i][k] = dist;
                        }
                    }
                }
            }
        }
    }

    private void calcDistMat() {
        distMat = new double[pointSize][pointSize];
        for (int i = 0; i < pointSize; i++) {
            for (int j = i + 1; j < pointSize; j++) {
                if (adjMat[i][j] == '1') {
                    distMat[i][j] = distMat[j][i] = calcDistance(i, j);
                } else {
                    distMat[i][j] = distMat[j][i] = INF;
                }
            }
        }
    }

    private void input() {
        pointSize = in.nextInt();
        points = new Point[pointSize];
        for (int i = 0; i < pointSize; i++) {
            points[i] = new Point(in.nextInt(), in.nextInt());
        }
        adjMat = new char[pointSize][];
        for (int i = 0; i < pointSize; i++) {
            adjMat[i] = in.next().toCharArray();
        }
    }

    private double calcDistance(int i, int j) {
        double a = points[i].x - points[j].x;
        double b = points[i].y - points[j].y;
        double c = a * a + b * b;
        return Math.sqrt(c);
    }

    static class Point {
        int x;
        int y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public static void main(String[] args) throws IOException {
        new cowtour().work();
    }
}
